package com.base.self.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.base.log.RequestUtils;
import com.base.result.PageUtils;
import com.base.result.ResponseResult;
import com.base.result.ResponseResultUtils;
import com.base.self.common.SelfRuntimeException;
import com.base.self.dto.commodity.*;
import com.base.self.entity.Commodity;
import com.base.self.entity.CommodityClassify;
import com.base.self.es.model.CommodityEs;
import com.base.self.es.repository.CommodityEsRepository;
import com.base.self.mapper.CommodityClassifyMapper;
import com.base.self.mapper.CommodityMapper;
import com.base.self.service.ICommodityService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.base.self.service.ISelfGoodsService;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 商品信息 服务实现类
 * </p>
 *
 * @author XiFYuW
 * @since 2020-11-15
 */
@Service
@Slf4j
public class CommodityServiceImpl extends ServiceImpl<CommodityMapper, Commodity> implements ICommodityService {

    private final CommodityClassifyMapper commodityClassifyMapper;

    private final CommodityMapper commodityMapper;

    private final ISelfGoodsService iSelfGoodsService;

    private final CommodityEsRepository commodityEsRepository;

    private final RequestUtils requestUtils;

    public CommodityServiceImpl(CommodityClassifyMapper commodityClassifyMapper,
                                CommodityMapper commodityMapper,
                                ISelfGoodsService iSelfGoodsService,
                                CommodityEsRepository commodityEsRepository,
                                RequestUtils requestUtils) {
        this.commodityClassifyMapper = commodityClassifyMapper;
        this.commodityMapper = commodityMapper;
        this.iSelfGoodsService = iSelfGoodsService;
        this.commodityEsRepository = commodityEsRepository;
        this.requestUtils = requestUtils;
    }

    @Override
    public ResponseResult commodityWebList(CommodityWebListDTO commodityWebListDTO) {
        if (!StringUtils.isEmpty(commodityWebListDTO.getCommodityName())) {
            QueryBuilder customerQuery = QueryBuilders.boolQuery()
                    .must(QueryBuilders.matchQuery("commodityName", commodityWebListDTO.getCommodityName()));
            org.springframework.data.domain.Page<CommodityEs> page = commodityEsRepository.search(
                    customerQuery,
                    PageRequest.of(commodityWebListDTO.getOffset() - 1, commodityWebListDTO.getLimit())
            );
            final List<Commodity> commodityList = new ArrayList<>();
            final List<CommodityEs> list = page.getContent();
            list.forEach(x -> {
                final Commodity commodity = commodityMapper.selectById(x.getId());
                setClassifyLevelName(commodity);
                commodityList.add(commodity);
            });
            Map<String, Object> data = new HashMap<>();
            data.put("total", page.getTotalElements());
            data.put("rows", commodityList);
            return ResponseResultUtils.getResponseResultS("查询成功", data);
        }

        final Integer commoditySubarea = commodityWebListDTO.getCommoditySubarea();
        final Integer commodityClassifyLevel1 = commodityWebListDTO.getCommodityClassifyLevel1();
        Map<String, Object> data = PageUtils.getDateMapBack(() -> page(PageUtils.getPage(
                new Page<>(), commodityWebListDTO.getOffset(), commodityWebListDTO.getLimit()),
                new LambdaQueryWrapper<Commodity>()
                        .eq(commodityClassifyLevel1 !=null && commodityClassifyLevel1 != 0, Commodity::getCommodityClassifyLevel1, commodityClassifyLevel1)
                        .eq(commoditySubarea !=null && commoditySubarea != 0, Commodity::getCommoditySubarea, commoditySubarea)
                        .orderByDesc(Commodity::getCreateTime))
                ,
                page -> {
                    List<Commodity> data1 = page.getRecords();
                    return data1.stream().peek(this::setClassifyLevelName).collect(Collectors.toList());
                }
        );
        return ResponseResultUtils.getResponseResultS("查询成功", data);
    }

    @Override
    public ResponseResult commodityWebAdd(CommodityWebAddDTO commodityWebAddDTO) {
        Map<String, Object> userMap = requestUtils.getUserData();
        checkClassifyLevel(commodityWebAddDTO.getCommodityClassifyLevel1(), commodityWebAddDTO.getCommodityClassifyLevel2());

        final BigDecimal commodityRealPrice;
        if (commodityWebAddDTO.getCommodityRealPrice().compareTo(BigDecimal.ZERO) <= 0) {
            commodityRealPrice = iSelfGoodsService.getGoodsPaymentPrice(commodityWebAddDTO.getCommodityMarketPrice());
        } else {
            commodityRealPrice = commodityWebAddDTO.getCommodityRealPrice();
        }
        final Commodity commodity = Commodity
                .builder()
                .commodityName(commodityWebAddDTO.getCommodityName())
                .commodityRealPrice(commodityRealPrice)
                .commodityMarketPrice(commodityWebAddDTO.getCommodityMarketPrice())
                .commodityStock(commodityWebAddDTO.getCommodityStock())
                .commodityStandard(commodityWebAddDTO.getCommodityStandard())
                .commoditySubarea(commodityWebAddDTO.getCommoditySubarea())
                .parentId(String.valueOf(userMap.get("parentId")))
                .shopId(String.valueOf(userMap.get("shopId")))
                .commodityExplain(commodityWebAddDTO.getCommodityExplain())
                .commodityContextDetails(commodityWebAddDTO.getCommodityContextDetails())
                .commodityClassifyLevel1(commodityWebAddDTO.getCommodityClassifyLevel1())
                .commodityClassifyLevel2(commodityWebAddDTO.getCommodityClassifyLevel2())
                .commodityShowPic(commodityWebAddDTO.getCommodityShowPic())
                .commoditySlidePic1(commodityWebAddDTO.getCommoditySlidePic1())
                .commoditySlidePic2(commodityWebAddDTO.getCommoditySlidePic2())
                .commoditySlidePic3(commodityWebAddDTO.getCommoditySlidePic3())
                .expirationHour(commodityWebAddDTO.getExpirationHour())
                .callPlan(commodityWebAddDTO.getCallPlan())
                .buy(commodityWebAddDTO.getBuy())
                .createTime(DateUtil.date())
                .commoditySales(RandomUtil.randomInt(1000))
                .build();
        save(commodity);
        try {/*商品入ES*/
            final CommodityEs commodityEs = getCommodityEs(commodity);
            commodityEsRepository.save(commodityEs);
        }catch (Exception e) {
            e.printStackTrace();
            log.warn("商品入ES错误：{}", commodity.getId());
        }

        return ResponseResultUtils.getResponseResultS("添加成功");
    }

    @Override
    public ResponseResult commodityWebDelete(CommodityWebDeleteDTO commodityWebDeleteDTO) {
        final Commodity commodity = commodityMapper.selectById(commodityWebDeleteDTO.getId());
        Optional.ofNullable(commodity).orElseThrow(() -> new SelfRuntimeException(ResponseResultUtils.getResponseResultF("商品信息错误")));
        commodity.setIsDel(commodityWebDeleteDTO.getIsDel());
        updateById(commodity);

        if (commodityWebDeleteDTO.getIsDel() == 0) {
            try {/*商品入ES*/
                final CommodityEs commodityEs = getCommodityEs(commodity);
                commodityEsRepository.save(commodityEs);
            }catch (Exception e) {
                e.printStackTrace();
                log.warn("商品入ES错误：{}", commodity.getId());
            }
        }

        if (commodityWebDeleteDTO.getIsDel() == 1) {
            try {/*ES删除商品*/
                final CommodityEs commodityEs = getCommodityEs(commodity);
                commodityEsRepository.delete(commodityEs);
            }catch (Exception e) {
                e.printStackTrace();
                log.warn("ES删除商品错误：{}", commodity.getId());
            }
        }

        return ResponseResultUtils.getResponseResultS(commodityWebDeleteDTO.getIsDel() == 0 ? "上架成功" : "下架成功");
    }

    @Override
    public ResponseResult commodityWebUpdate(CommodityWebUpdateDTO commodityWebUpdateDTO) {
        final Commodity commodity = commodityMapper.selectById(commodityWebUpdateDTO.getId());
        Optional.ofNullable(commodity).orElseThrow(() -> new SelfRuntimeException(ResponseResultUtils.getResponseResultF("商品信息错误")));
        checkClassifyLevel(commodityWebUpdateDTO.getCommodityClassifyLevel1(), commodityWebUpdateDTO.getCommodityClassifyLevel2());

        commodity.setId(commodity.getId());
        commodity.setParentId(commodity.getParentId());
        commodity.setUpdateTime(DateUtil.date());
        commodity.setCommodityClassifyLevel1(commodityWebUpdateDTO.getCommodityClassifyLevel1());
        commodity.setCommodityClassifyLevel2(commodityWebUpdateDTO.getCommodityClassifyLevel2());
        commodity.setCommodityName(commodityWebUpdateDTO.getCommodityName());
        commodity.setCommodityContextDetails(commodityWebUpdateDTO.getCommodityContextDetails());
        commodity.setCommodityExplain(commodityWebUpdateDTO.getCommodityExplain());
        commodity.setCommodityMarketPrice(commodityWebUpdateDTO.getCommodityMarketPrice());
        commodity.setCommodityRealPrice(commodityWebUpdateDTO.getCommodityRealPrice());
        commodity.setCommodityShowPic(commodityWebUpdateDTO.getCommodityShowPic());
        commodity.setCommoditySlidePic1(commodityWebUpdateDTO.getCommoditySlidePic1());
        commodity.setCommoditySlidePic2(commodityWebUpdateDTO.getCommoditySlidePic2());
        commodity.setCommoditySlidePic3(commodityWebUpdateDTO.getCommoditySlidePic3());
        commodity.setCommodityStandard(commodityWebUpdateDTO.getCommodityStandard());
        commodity.setCommodityStock(commodityWebUpdateDTO.getCommodityStock());
        commodity.setCommoditySubarea(commodityWebUpdateDTO.getCommoditySubarea());
        commodity.setExpirationHour(commodityWebUpdateDTO.getExpirationHour());
        commodity.setCallPlan(commodityWebUpdateDTO.getCallPlan());
        commodity.setCommoditySales(commodityWebUpdateDTO.getCommoditySales());
        commodity.setBuy(commodityWebUpdateDTO.getBuy());
        updateById(commodity);

        try {/*ES更新商品*/
            final CommodityEs commodityEs = getCommodityEs(commodity);
            commodityEsRepository.delete(commodityEs);
            commodityEsRepository.save(commodityEs);
        }catch (Exception e) {
            e.printStackTrace();
            log.warn("ES更新商品错误：{}", commodity.getId());
        }
        return ResponseResultUtils.getResponseResultS("修改成功");
    }

    @Override
    public ResponseResult commodityWebDetail(CommodityWebDetailDTO commodityWebDetailDTO) {
        final Commodity commodity = commodityMapper.selectById(commodityWebDetailDTO.getCommodityId());
        Optional.ofNullable(commodity).orElseThrow(() -> new SelfRuntimeException(ResponseResultUtils.getResponseResultF("商品信息错误")));
        return ResponseResultUtils.getResponseResultS("查询成功", commodity);
    }

    private void checkClassifyLevel(final Integer classifyLevel1, final Integer classifyLevel2) {
        if (classifyLevel1 != null) {
            Optional.ofNullable(
                    commodityClassifyMapper.selectOne(new QueryWrapper<CommodityClassify>()
                            .eq("is_del", 0)
                            .eq("id", classifyLevel1)
                    )
            ).orElseThrow(() -> new SelfRuntimeException(ResponseResultUtils.getResponseResultF("商品一级分类错误")));
        }

        if (classifyLevel2 != null && !classifyLevel2.equals(0)) {
            Optional.ofNullable(
                    commodityClassifyMapper.selectOne(new QueryWrapper<CommodityClassify>()
                            .eq("is_del", 0)
                            .eq("id", classifyLevel2)
                    )
            ).orElseThrow(() -> new SelfRuntimeException(ResponseResultUtils.getResponseResultF("商品二级分类错误")));
        }

    }

    private void setClassifyLevelName(final Commodity x){
        Optional.ofNullable(
                commodityClassifyMapper.selectOne(
                        new LambdaQueryWrapper<CommodityClassify>()
                                .eq(CommodityClassify::getId, x.getCommodityClassifyLevel1())
                                .eq(CommodityClassify::getIsDel, 0)
                )
        ).ifPresent(c -> x.setCommodityClassifyLevelName1(c.getClassifyName()));
        Optional.ofNullable(
                commodityClassifyMapper.selectOne(
                        new LambdaQueryWrapper<CommodityClassify>()
                                .eq(CommodityClassify::getId, x.getCommodityClassifyLevel2())
                                .eq(CommodityClassify::getIsDel, 0)
                )
        ).ifPresent(c -> x.setCommodityClassifyLevelName2(c.getClassifyName()));
    }

    private CommodityEs getCommodityEs(final Commodity commodity){
        return CommodityEs
                .builder()
                .id(commodity.getId())
                .commodityMarketPrice(commodity.getCommodityMarketPrice())
                .commodityName(commodity.getCommodityName())
                .commodityRealPrice(commodity.getCommodityRealPrice())
                .commoditySales(commodity.getCommoditySales())
                .commodityShowPic(commodity.getCommodityShowPic())
                .createTime(commodity.getCreateTime())
                .commoditySubarea(commodity.getCommoditySubarea())
                .commodityClassifyLevel2(commodity.getCommodityClassifyLevel2())
                .commodityClassifyLevel1(commodity.getCommodityClassifyLevel1())
                .build();
    }
}
